#pragma once
#include<iostream>
#include<set>
#include"Transaction.h"
#include"ResourcePool.h"
using namespace std;


class CheckIsInUtil{
public:

    static vector<Basic*> getSortDataVec(const vector<Basic*>& unSortDataVec){
        vector<Basic*> sortDataVec = unSortDataVec;
        sort(sortDataVec.begin(), sortDataVec.end(), basicCmp);
        return sortDataVec;
    }

    static bool isInSortVec(const vector<Basic*>& sortDataVec, const Basic* data){
        int left = 0, right = sortDataVec.size() - 1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            Basic* midVal = sortDataVec[mid];
            if(basicEqu(midVal, data)){
                return true;
            }
            else if(basicCmp(midVal, data)){
                left = mid + 1;
            }
            else{
                right = mid - 1;
            }
        }
        return false;
    }
};

class ResourceUtil{
public:

    static map<ResourceInfo, vector<pair<Basic*, size_t>>> getMergeIndexOrBitMapInfoAccrodData(const TableInfo* tableInfo, const string& colName, const vector<Basic*>& targetDataVec, const bool& isIndex){
        map<ResourceInfo, vector<pair<Basic*, size_t>>> mergeInfo;
        for(size_t i = 0; i < targetDataVec.size(); i++){
            Basic* targetData = targetDataVec[i];
            const ResourceInfo& resInfo = isIndex ?
                                                  tableInfo->getProbIndResInfo(colName, targetData->getHashVal()) :
                                                  tableInfo->getProbBitMapResInfo(colName, targetData->getHashVal());
            mergeInfo[resInfo].push_back(make_pair(targetData, i));
        }
        return mergeInfo;
    }

    static vector<ResourceManage*> getSortResVec(const vector<ResourceManage*>& resVec){
        vector<ResourceManage*> sortedResVec(resVec.begin(), resVec.end());
        sort(sortedResVec.begin(), sortedResVec.end(), resCmp);
        return sortedResVec;
    }

    static void getResLock(const vector<ResourceManage*>& resVec, const LOCKTYPE& lockType, Transaction* transaction){
        const vector<ResourceManage*>& sortResVec = getSortResVec(resVec);    //获取有序的 按序获取锁 减少死锁
        if(transaction == nullptr){
            for(ResourceManage* tmpRes : sortResVec){
                tmpRes->getResLock(lockType);
            }
        }
        else{
            for(ResourceManage* tmpRes : sortResVec){
                transaction->getResLock(tmpRes, lockType); //没获取到会抛异常
            }
        }
    }



    static void releaseResLock(const vector<ResourceManage*>& resVec){
        for(ResourceManage* tmpRes : resVec){
            tmpRes->releaseResLock();
        }
    }

    static void getHoldLock(const vector<ResourceManage*>& resVec, const LOCKTYPE& lockType){
        const vector<ResourceManage*>& sortResVec = getSortResVec(resVec);    //获取有序的 按序获取锁 减少死锁
        for(ResourceManage* res : sortResVec){
            res->getHoldLock(lockType);
        }
    }

    static void releaseHoldLock(const vector<ResourceManage*>& resVec){
        for(ResourceManage* tmpRes : resVec){
            tmpRes->releaseHoldLock();
        }
    }

    static void getSnapShotLock(const vector<ResourceManage*>& resVec, const LOCKTYPE& lockType){
        const vector<ResourceManage*>& sortResVec = getSortResVec(resVec);    //获取有序的 按序获取锁 减少死锁
        for(ResourceManage* res : sortResVec){
            res->getSnapShotLock(lockType);
        }
    }


    static void releaseSnapShotLock(const vector<ResourceManage*>& resVec){
        for(ResourceManage* tmpRes : resVec){
            tmpRes->releaseSnapShotLock();
        }
    }


    static vector<ResourceInfo> getRowBlockInfo(const TableInfo* tableInfo, const vector<string>& colNameVec, const int16_t& blockNo){
        vector<ResourceInfo> blockInfoVec;
        const string& baseName = tableInfo->getBaseName(), tableName = tableInfo->getTableName();
        for(const string& colName : colNameVec){
            const TYPE& dataType = tableInfo->getColInfo(colName)->getDataType();
            blockInfoVec.push_back(ResourceInfo(baseName, tableName, colName, blockNo, dataType));
        }
        return blockInfoVec;
    }


    static vector<ResourceInfo> getRowBlockInfo(const TableInfo* tableInfo, const int16_t& blockNo){
        return getRowBlockInfo(tableInfo, tableInfo->getColNameVec(false), blockNo);
    }


    static ResourceManage* getRes(const ResourceInfo& resInfo, Transaction* transaction){
        if(transaction == nullptr){
            return ResourcePool::getRes(resInfo);
        }
        ResourceManage* res = transaction->getRes(resInfo);
        if(res == nullptr){
            res = ResourcePool::getRes(resInfo);    //在从资源池获取的时候就已经标记持有资源了
            transaction->putRes(res);
        }
        return res;
    }

    static vector<ResourceManage*> getResVec(const vector<ResourceInfo>& resInfoVec, Transaction* transaction){
        vector<ResourceManage*> blockVec;
        for(const ResourceInfo& resInfo : resInfoVec){
            blockVec.push_back(getRes(resInfo, transaction));
        }
        return blockVec;
    }
};
